<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 The Robots of Dawn
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora194.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora196.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> The Robots of Dawn</H2>
<A NAME="app-robby"></A>As we promised in the last application of the third part (page
<A HREF="book-ora161.html#app-robot">??</A>), we will now revisit the problem of robots in order to
treat it in a distributed framework where the world is a server and where each
robot is an independent process capable of being executed on a remote machine.<BR>
<BR>
This application is a good summary of the possibilities of the Objective CAML
language because we will utilize and combine the majority of its features.
In addition to the distributed model which is imposed on us by the exercise,
we will make use of concurrency to construct a server in which multiple
connections will be handled independently while all sharing a single memory
representation of the ``world''. All access to and modification of the state
of affairs of the world will therefore have to be protected by critical
sections.<BR>
<BR>
In order to reuse as much as possible the code that we have already built
for robots in one section, and the client-server architecture of another
section, we will use functors and inheritance of classes at the same time.<BR>
<BR>
This application is quite minimal, but we will see that its architecture lends
itself particularly well to extensions in multiple directions.<BR>
<BR>
<A NAME="toc294"></A>
<H3> World-Server</H3>We take a representation of the world similar to that which we developed in
Part III. The world is a grid of finite size, and each cell of the grid can
be occupied by only one robot. A robot is identified by its name and by its
position; the world is determined by its size and by the robots that live in
it. This information is represented by the following types:<BR>
<BR>


<PRE><BR># <B>type</B><CODE> </CODE>position<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>x<CODE>:</CODE>int<CODE> </CODE>;<CODE> </CODE>y<CODE>:</CODE>int<CODE> </CODE>}<CODE> </CODE>;;<BR><BR># <B>type</B><CODE> </CODE>robot_info<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>name<CODE> </CODE><CODE>:</CODE><CODE> </CODE>string<CODE> </CODE>;<CODE> </CODE><B>mutable</B><CODE> </CODE>pos<CODE> </CODE><CODE>:</CODE><CODE> </CODE>position<CODE> </CODE>}<CODE> </CODE><BR><CODE> </CODE><B>type</B><CODE> </CODE>world_info<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>length<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE>;<CODE> </CODE>width<CODE> </CODE><CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>mutable</B><CODE> </CODE>robots<CODE> </CODE><CODE>:</CODE><CODE> </CODE>robot_info<CODE> </CODE>list<CODE> </CODE>}<CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The world will have to serve two sorts of clients:
<UL>
<LI> 
 passive clients which simply observe the positions of various robots.
They will allow us to build the clients in charge of displays. We will call
them spies.

<LI> active clients, able to ask the server to move robots and thus modify
its state.
</UL>
These two categories of clients and their behavior will determine the
collection of messages exchanged by the server and clients.<BR>
<BR>
When a client connects, it declares itself passive (<TT>Spy</TT>) or active
(<TT>Enter</TT>). A spy receives as response to its connection the global
state of the world. Then, it is kept informed of all changes. However, it
cannot submit any requests. A robot which connects must supply its
characteristics (its name and its initial position); the world then confirms
its arrival. Then, it can request information: its own position
(<TT>GetPos</TT>) or the list of robots that surround it (<TT>Look</TT>). It
can also instruct the world to move it. The protocol of requests to the world
from distributed robots is represented by the following type:


<PRE><BR># <B>type</B><CODE> </CODE>query<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Spy<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* initial declaration requests *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Enter<CODE> </CODE><B>of</B><CODE> </CODE>robot_info<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Move<CODE> </CODE><B>of</B><CODE> </CODE>position<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* robot requests *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>GetPos<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Look<CODE> </CODE><B>of</B><CODE> </CODE>int<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>World<CODE> </CODE><B>of</B><CODE> </CODE>world_info<CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>(* messages delivered by the world *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Pos<CODE> </CODE><B>of</B><CODE> </CODE>robot_info<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Exit<CODE> </CODE><B>of</B><CODE> </CODE>robot_info<CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
From this protocol, using the functors from the ``distributed toolbox'' of
the previous chapter, we immediately derive the generic server.


<PRE><BR># <B>module</B><CODE> </CODE>Pquery<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Make_Protocol<CODE> </CODE><TT>(</TT><B>struct</B><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>query<CODE> </CODE><B>end</B><CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR># <B>module</B><CODE> </CODE>Squery<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Server<CODE> </CODE><TT>(</TT>Pquery<TT>)</TT><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
Now we need only specify the behavior of the server by implementing the
method <TT>process</TT> to handle both the data that represent the world
and the data for managing connections.<BR>
<BR>
More precisely, the server contains a variable <TT>world</TT> (of type
<I>world_info</I>) which is protected by the lock <TT>sem</TT> (of type
<I>Mutex.t</I>). It also contains a variable <TT>spies</TT> which is a list
of queues of messages to send to observers, with one queue per spy. To
activate the processes in charge of sending these messages, the server also
maintains a signal (of type <I>Condition.t</I>).<BR>
<BR>
We provide an auxiliary function <TT>dist</TT> to calculate the distance
between two positions:


<PRE><BR># <B>let</B><CODE> </CODE>dist<CODE> </CODE>p<CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><CODE> </CODE>max<CODE> </CODE><TT>(</TT>abs<CODE> </CODE><TT>(</TT>p<CODE>.</CODE>x<CODE>-</CODE>q<CODE>.</CODE>x<TT>)</TT><TT>)</TT><CODE> </CODE><TT>(</TT>abs<CODE> </CODE><TT>(</TT>p<CODE>.</CODE>y<CODE>-</CODE>q<CODE>.</CODE>y<TT>)</TT><TT>)</TT><CODE> </CODE>;;<BR><CODE>val dist : position -&gt; position -&gt; int = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The function <TT>critical</TT> encapsulates the calculation of a value within
a critical section:


<PRE><BR># <B>let</B><CODE> </CODE>critical<CODE> </CODE>m<CODE> </CODE>f<CODE> </CODE>a<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Mutex.lock<CODE> </CODE>m<CODE> </CODE>;<CODE> </CODE><B>let</B><CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>f<CODE> </CODE>a<CODE> </CODE><B>in</B><CODE> </CODE>Mutex.unlock<CODE> </CODE>m<CODE> </CODE>;<CODE> </CODE>r<CODE> </CODE>;;<BR><CODE>val critical : Mutex.t -&gt; ('a -&gt; 'b) -&gt; 'a -&gt; 'b = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Here is the definition of the class <TT>server</TT> implementing the
world-server. It is long, but we will follow it up with a step-by-step
explanation.


<PRE><BR># <B>class</B><CODE> </CODE><CODE> </CODE>server<CODE> </CODE>l<CODE> </CODE>w<CODE> </CODE>n<CODE> </CODE>np<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE><CODE>[</CODE>query<CODE>]</CODE><CODE> </CODE>Squery.server<CODE> </CODE>n<CODE> </CODE>np<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>world<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>length<CODE>=</CODE>l<CODE> </CODE>;<CODE> </CODE>width<CODE>=</CODE>w<CODE> </CODE>;<CODE> </CODE>robots<CODE>=[]</CODE><CODE> </CODE>}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>sem<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Mutex.create<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>spies<CODE> </CODE><CODE>=</CODE><CODE> </CODE>[]<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>signal<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Condition.create<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>lock<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Mutex.lock<CODE> </CODE>sem<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>unlock<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Mutex.unlock<CODE> </CODE>sem<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>legal_pos<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>p<CODE>.</CODE>x<CODE>&gt;=</CODE><CODE>0</CODE><CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>p<CODE>.</CODE>x<CODE>&lt;</CODE>l<CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>p<CODE>.</CODE>y<CODE>&gt;=</CODE><CODE>0</CODE><CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>p<CODE>.</CODE>y<CODE>&lt;</CODE>w<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>free_pos<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>is_not_here<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>x<CODE>&lt;&gt;</CODE>p<CODE>.</CODE>x<CODE> </CODE><CODE>||</CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>y<CODE>&lt;&gt;</CODE>p<CODE>.</CODE>y<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>critical<CODE> </CODE>sem<CODE> </CODE><TT>(</TT>List.for_all<CODE> </CODE>is_not_here<TT>)</TT><CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>legal_move<CODE> </CODE>r<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>dist1<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>dist<CODE> </CODE>r<CODE>.</CODE>pos<CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE>&lt;=</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><TT>(</TT>critical<CODE> </CODE>sem<CODE> </CODE>dist1<CODE> </CODE>p<TT>)</TT><CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>self#legal_pos<CODE> </CODE>p<CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>self#free_pos<CODE> </CODE>p<CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>queue_message<CODE> </CODE>mes<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>List.iter<CODE> </CODE><TT>(</TT>Queue.add<CODE> </CODE>mes<TT>)</TT><CODE> </CODE>spies<CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Condition.broadcast<CODE> </CODE>signal<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>trace_loop<CODE> </CODE>s<CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>foo<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Mutex.create<CODE> </CODE>()<CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>f<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>spies<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>q<CODE> </CODE>::<CODE> </CODE>spies<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#send<CODE> </CODE>s<CODE> </CODE><TT>(</TT>World<CODE> </CODE>world<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE>Queue.length<CODE> </CODE>q<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>do</B><CODE> </CODE>Condition.wait<CODE> </CODE>signal<CODE> </CODE>foo<CODE> </CODE><B>done</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#send<CODE> </CODE>s<CODE> </CODE><TT>(</TT>Queue.take<CODE> </CODE>q<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>spies<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>List.filter<CODE> </CODE><TT>(</TT><TT>(</TT><CODE>!=</CODE><TT>)</TT><CODE> </CODE>q<TT>)</TT><CODE> </CODE>spies<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Unix.close<CODE> </CODE>s<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>ignore<CODE> </CODE><TT>(</TT>Thread.create<CODE> </CODE>f<CODE> </CODE>()<TT>)</TT><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>remove_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#lock<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>List.filter<CODE> </CODE><TT>(</TT><TT>(</TT><CODE>&lt;&gt;</CODE><TT>)</TT><CODE> </CODE>r<TT>)</TT><CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#queue_message<CODE> </CODE><TT>(</TT>Exit<CODE> </CODE>{r<CODE> </CODE><B>with</B><CODE> </CODE>name<CODE>=</CODE>r<CODE>.</CODE>name}<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#unlock<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>try_move_robot<CODE> </CODE>r<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>self#legal_move<CODE> </CODE>r<CODE> </CODE>p<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE><B>begin</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#lock<CODE> </CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>p<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#queue_message<CODE> </CODE><TT>(</TT>Pos<CODE> </CODE>{r<CODE> </CODE><B>with</B><CODE> </CODE>name<CODE>=</CODE>r<CODE>.</CODE>name}<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#unlock<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>process_robot<CODE> </CODE>s<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>f<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r<CODE> </CODE>::<CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#send<CODE> </CODE>s<CODE> </CODE><TT>(</TT>Pos<CODE> </CODE>r<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#queue_message<CODE> </CODE><TT>(</TT>Pos<CODE> </CODE>r<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Thread.delay<CODE> </CODE><CODE>0</CODE><CODE>.</CODE><CODE>5</CODE><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>self#receive<CODE> </CODE>s<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Move<CODE> </CODE>p<CODE> </CODE>-&gt;<CODE> </CODE>self#try_move_robot<CODE> </CODE>r<CODE> </CODE>p<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>GetPos<CODE> </CODE>-&gt;<CODE> </CODE>self#send<CODE> </CODE>s<CODE> </CODE><TT>(</TT>Pos<CODE> </CODE>r<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Look<CODE> </CODE>d<CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#lock<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>dist<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>max<CODE> </CODE><TT>(</TT>abs<CODE> </CODE><TT>(</TT>p<CODE>.</CODE>x<CODE>-</CODE>r<CODE>.</CODE>pos<CODE>.</CODE>x<TT>)</TT><TT>)</TT><CODE> </CODE><TT>(</TT>abs<CODE> </CODE><TT>(</TT>p<CODE>.</CODE>y<CODE>-</CODE>r<CODE>.</CODE>pos<CODE>.</CODE>y<TT>)</TT><TT>)</TT><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>l<CODE> </CODE><CODE>=</CODE><CODE> </CODE>List.filter<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>dist<CODE> </CODE>x<CODE>.</CODE>pos<TT>)</TT><CODE>&lt;=</CODE>d<TT>)</TT><CODE> </CODE>world<CODE>.</CODE>robots<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>self#send<CODE> </CODE>s<CODE> </CODE><TT>(</TT>World<CODE> </CODE>{<CODE> </CODE>world<CODE> </CODE><B>with</B><CODE> </CODE>robots<CODE> </CODE><CODE>=</CODE><CODE> </CODE>l<CODE> </CODE>}<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#unlock<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>self#unlock<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#remove_robot<CODE> </CODE>r<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Unix.close<CODE> </CODE>s<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>ignore<CODE> </CODE><TT>(</TT>Thread.create<CODE> </CODE>f<CODE> </CODE>()<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>process<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>self#receive<CODE> </CODE>s<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Spy<CODE> </CODE>-&gt;<CODE> </CODE>self#trace_loop<CODE> </CODE>s<CODE> </CODE><TT>(</TT>Queue.create<CODE> </CODE>()<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Enter<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>if</B><CODE> </CODE>not<CODE> </CODE><TT>(</TT>self#legal_pos<CODE> </CODE>r<CODE>.</CODE>pos<CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>self#free_pos<CODE> </CODE>r<CODE>.</CODE>pos<TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>and</B><CODE> </CODE>j<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>try</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>for</B><CODE> </CODE>x<CODE>=</CODE><CODE>0</CODE><CODE> </CODE><B>to</B><CODE> </CODE>l<CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>for</B><CODE> </CODE>y<CODE>=</CODE><CODE>0</CODE><CODE> </CODE><B>to</B><CODE> </CODE>w<CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>x<CODE>=</CODE>x<CODE> </CODE>;<CODE> </CODE>y<CODE>=</CODE>y<CODE> </CODE>}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>if</B><CODE> </CODE>self#legal_pos<CODE> </CODE>p<CODE> </CODE><CODE>&amp;&amp;</CODE><CODE> </CODE>self#free_pos<CODE> </CODE>p<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE><TT>(</TT><CODE> </CODE>i<CODE>:=</CODE>x<CODE> </CODE>;<CODE> </CODE>j<CODE>:=</CODE>y;<CODE> </CODE>failwith<CODE> </CODE><CODE>"process"</CODE><CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><CODE> </CODE><B>done</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Unix.close<CODE> </CODE>s<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE>Failure<CODE> </CODE><CODE>"process"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>r<CODE>.</CODE>pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>{<CODE> </CODE>x<CODE>=</CODE><CODE> </CODE><CODE>!</CODE>i<CODE> </CODE>;<CODE> </CODE>y<CODE>=</CODE><CODE> </CODE><CODE>!</CODE>j<CODE> </CODE>}<CODE> </CODE><CODE> </CODE><TT>)</TT><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>self#process_robot<CODE> </CODE>s<CODE> </CODE>r<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>Unix.close<CODE> </CODE>s<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class server :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val nb_pending : int</CODE><BR><CODE>    val port_num : int</CODE><BR><CODE>    val sem : Mutex.t</CODE><BR><CODE>    val signal : Condition.t</CODE><BR><CODE>    val sock : Unix.file_descr</CODE><BR><CODE>    val mutable spies : Pquery.t Queue.t list</CODE><BR><CODE>    val world : world_info</CODE><BR><CODE>    method free_pos : position -&gt; bool</CODE><BR><CODE>    method legal_move : robot_info -&gt; position -&gt; bool</CODE><BR><CODE>    method legal_pos : position -&gt; bool</CODE><BR><CODE>    method lock : unit</CODE><BR><CODE>    method process : Unix.file_descr -&gt; unit</CODE><BR><CODE>    method process_robot : Unix.file_descr -&gt; robot_info -&gt; unit</CODE><BR><CODE>    method queue_message : Pquery.t -&gt; unit</CODE><BR><CODE>    method receive : Unix.file_descr -&gt; Pquery.t</CODE><BR><CODE>    method remove_robot : robot_info -&gt; unit</CODE><BR><CODE>    method send : Unix.file_descr -&gt; Pquery.t -&gt; unit</CODE><BR><CODE>    method start : unit</CODE><BR><CODE>    method trace_loop : Unix.file_descr -&gt; Pquery.t Queue.t -&gt; unit</CODE><BR><CODE>    method try_move_robot : robot_info -&gt; position -&gt; unit</CODE><BR><CODE>    method unlock : unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
The method <TT>process</TT> starts out by distinguishing between the two
types of client. Depending on whether the client is active or passive, it
invokes a processing method called: <TT>trace_loop</TT> for an observer,
<TT>process_robot</TT> for a robot. In the second case, it checks that
the initial position proposed by the client is compatible with the state of
the world; if not, it finds a valid initial position. The remainder of the
code can be divided into four categories:
<OL type=1>
<LI>
 <B>General methods</B>: these are methods which we developed in Part III
for general worlds. Mainly, it is a matter of verifying that a displacement is
legal for a given robot.

<LI> <B>Management of observers</B>: each observer is associated with a socket
through which it is sent data, with a queue containing all the messages which
have not yet been sent to it, and with a process. The method
<TT>trace_loop</TT> is an infinite loop that empties the queue of messages by
sending them; it goes to sleep when the queue is empty. The queues are filled,
all at the same time, by the method <TT>queue_message</TT>. Note that after
appending a message, the activation signal is sent to all processes.

<LI> <B>Management of robots</B>: here again, each robot is associated with a
dedicated process. The method <TT>process_robot</TT> is an infinite loop: it
waits for a request, processes it, and responds if necessary. Then it resumes
waiting for the next request. Note that it is these robot-management methods
which issue calls to the method <TT>queue_message</TT> when the state of the
world has been modified. If the connection with a robot is lost---that is, if
an exception is raised while waiting for a request---the robot is considered
to have terminated and its departure is signaled to the observers.

<LI> <B>Inherited methods</B>: these are the methods of the generic server
obtained by application of the functor <TT>Server</TT> to the protocol of our
application.
</OL><A NAME="toc295"></A>
<H3> Observer-client</H3>The functor <TT>Client</TT> gives us generic functions for connecting
with a server according to the particular protocol that concerns us here.


<PRE><BR># <B>module</B><CODE> </CODE>Cquery<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Client<CODE> </CODE><TT>(</TT>Pquery<TT>)</TT><CODE> </CODE>;;<BR><CODE>module Cquery :</CODE><BR><CODE>  sig</CODE><BR><CODE>    module Com :</CODE><BR><CODE>      sig</CODE><BR><CODE>        val send : Unix.file_descr -&gt; Pquery.t -&gt; unit</CODE><BR><CODE>        val receive : Unix.file_descr -&gt; Pquery.t</CODE><BR><CODE>      end</CODE><BR><CODE>    val connect : string -&gt; int -&gt; Unix.file_descr</CODE><BR><CODE>    val emit_simple : string -&gt; int -&gt; Pquery.t -&gt; unit</CODE><BR><CODE>    val emit_answer : string -&gt; int -&gt; Pquery.t -&gt; Pquery.t</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
The behavior of a spy is simple: it connects to the server and displays
the information that the server sends it. The spy includes three display
functions which we provide below:


<PRE><BR># <B>let</B><CODE> </CODE>display_robot<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"The robot %s is located at (%d,%d)\n"</CODE><CODE> </CODE>r<CODE>.</CODE>name<CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>x<CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>y<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>flush<CODE> </CODE>stdout<CODE> </CODE>;;<BR><CODE>val display_robot : robot_info -&gt; unit = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>display_exit<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"The robot %s has terminated\n"</CODE><CODE> </CODE>r<CODE>.</CODE>name<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>flush<CODE> </CODE>stdout<CODE> </CODE>;;<BR><CODE>val display_exit : robot_info -&gt; unit = &lt;fun&gt;</CODE><BR><BR># <B>let</B><CODE> </CODE>display_world<CODE> </CODE>w<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Printf.printf<CODE> </CODE><CODE>"The world is a grid of size %d by %d \n"</CODE><CODE> </CODE>w<CODE>.</CODE>length<CODE> </CODE>w<CODE>.</CODE>width<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>List.iter<CODE> </CODE>display_robot<CODE> </CODE>w<CODE>.</CODE>robots<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>flush<CODE> </CODE>stdout<CODE> </CODE>;;<BR><CODE>val display_world : world_info -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The primary function of the spy-client is:


<PRE><BR># <B>let</B><CODE> </CODE>trace_client<CODE> </CODE>name<CODE> </CODE>port<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>sock<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Cquery.connect<CODE> </CODE>name<CODE> </CODE>port<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.send<CODE> </CODE>sock<CODE> </CODE>Spy<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>match</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.receive<CODE> </CODE>sock<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>World<CODE> </CODE>w<CODE> </CODE>-&gt;<CODE> </CODE>display_world<CODE> </CODE>w<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"the server did not follow the protocol"</CODE><CODE> </CODE><TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.receive<CODE> </CODE>sock<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Pos<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>display_robot<CODE> </CODE>r<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>Exit<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>display_exit<CODE> </CODE>r<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"the server did not follow the protocol"</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><CODE> </CODE>;;<BR><CODE>val trace_client : string -&gt; int -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
There are two ways of constructing a graphical display. The first is
simple but not very efficient: since the server sends the complete set of
information when a connection is established, one can simply open a new
connection at regular intervals, display the world in its entirety, and
close the connection. The other approach involves using the information
sent by the server to maintain a copy of the state of the world. It is then
easy to display only the modifications to the state upon reception of
messages. It is this second solution which we have implemented.<BR>
<BR>
<A NAME="toc296"></A>
<H3> Robot-Client</H3>As we defined them in the previous chapter (cf. page <A HREF="book-ora161.html#app-robot">??</A>),
the robots conform to the following signature.<BR>
<BR>


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>ROBOT<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>class</B><CODE> </CODE>robot<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>i<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>j<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_pos<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>next_pos<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>set_pos<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE><CODE>*</CODE><CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The part that we wish to save from the various classes is that which
necessarily varies from one type of robot to another and which defines its
behavior: the method <TT>next_pos</TT>.<BR>
<BR>
In addition, we need a method for connecting the robot to the world
(<TT>start</TT>) and a loop that alternately calculates a new position and
communicates with the server to submit the chosen position.<BR>
<BR>
We define a functor which, when given a class implementing a virtual robot
(that is, conforming to the signature <TT>ROBOT</TT>), creates, by
inheritance, a new class containing the proper methods to make an autonomous
client out of the robot.<BR>
<BR>


<PRE><BR># <B>module</B><CODE> </CODE>RobotClient<CODE> </CODE><TT>(</TT>R<CODE> </CODE><CODE>:</CODE><CODE> </CODE>ROBOT<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>struct</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>class</B><CODE> </CODE>robot<CODE> </CODE>robname<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>hostname<CODE> </CODE>port<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><CODE> </CODE><TT>(</TT>self<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>R.robot<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><B>as</B><CODE> </CODE>super<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>socket<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Unix.stderr<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>rob<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>name<CODE>=</CODE>robname<CODE> </CODE>;<CODE> </CODE>pos<CODE>={</CODE>x<CODE>=</CODE>x;y<CODE>=</CODE>y}<CODE> </CODE>}<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE><B>private</B><CODE> </CODE>adjust_pos<CODE> </CODE>r<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>rob<CODE>.</CODE>pos<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE> </CODE>;<CODE> </CODE>i<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>x<CODE> </CODE>;<CODE> </CODE>j<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>r<CODE>.</CODE>pos<CODE>.</CODE>y<BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_pos<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Cquery<CODE>.</CODE>Com.send<CODE> </CODE>socket<CODE> </CODE>GetPos<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.receive<CODE> </CODE>socket<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Pos<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>self#adjust_pos<CODE> </CODE>r<CODE> </CODE>;<CODE> </CODE>super#get_pos<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"the server did not follow the protocol"</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>set_pos<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>failwith<CODE> </CODE><CODE>"the method set_pos cannot be used"</CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>start<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>socket<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>Cquery.connect<CODE> </CODE>hostname<CODE> </CODE>port<CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Cquery<CODE>.</CODE>Com.send<CODE> </CODE>socket<CODE> </CODE><TT>(</TT>Enter<CODE> </CODE>rob<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.receive<CODE> </CODE>socket<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Pos<CODE> </CODE>r<CODE> </CODE>-&gt;<CODE> </CODE>self#adjust_pos<CODE> </CODE>r<CODE> </CODE>;<CODE> </CODE>self#run<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><CODE>"the server did not follow the protocol"</CODE><CODE> </CODE><BR><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>run<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>self#next_pos<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>Cquery<CODE>.</CODE>Com.send<CODE> </CODE>socket<CODE> </CODE><TT>(</TT>Move<CODE> </CODE>{x<CODE>=</CODE>x;y<CODE>=</CODE>y}<TT>)</TT><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>ignore<CODE> </CODE><TT>(</TT>self#get_pos<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>module RobotClient :</CODE><BR><CODE>  functor(R : ROBOT) -&gt;</CODE><BR><CODE>    sig</CODE><BR><CODE>      class robot :</CODE><BR><CODE>        string -&gt;</CODE><BR><CODE>        int -&gt;</CODE><BR><CODE>        int -&gt;</CODE><BR><CODE>        string -&gt;</CODE><BR><CODE>        int -&gt;</CODE><BR><CODE>        object</CODE><BR><CODE>          val mutable i : int</CODE><BR><CODE>          val mutable j : int</CODE><BR><CODE>          val mutable rob : robot_info</CODE><BR><CODE>          val mutable socket : Unix.file_descr</CODE><BR><CODE>          method private adjust_pos : robot_info -&gt; unit</CODE><BR><CODE>          method get_pos : int * int</CODE><BR><CODE>          method next_pos : unit -&gt; int * int</CODE><BR><CODE>          method run : unit</CODE><BR><CODE>          method set_pos : int * int -&gt; unit</CODE><BR><CODE>          method start : unit</CODE><BR><CODE>        end</CODE><BR><CODE>    end</CODE><BR>

</PRE>
<BR>
<BR>
Notice that the method <TT>get_pos</TT> has been redefined as a query to the
server: the instance variables <TT>i</TT> and <TT>j</TT> are not reliable,
because they can be modified without the consent of the world. For the same
reason, the use of <TT>set_pos</TT> has been made invalid: calling it will
always raise an exception. This policy may seem severe, but it's a good bet
that if this method were used by <TT>next_pos</TT> then a discrepancy would
appear between the real position (as known by the server) and the supposed
position (as known by the client).<BR>
<BR>
We use the functor <TT>RobotClient</TT> to create various classes
corresponding to the various robots.<BR>
<BR>


<PRE><BR># <B>module</B><CODE> </CODE>Fix<CODE> </CODE><CODE>=</CODE><CODE> </CODE>RobotClient<CODE> </CODE><TT>(</TT><B>struct</B><CODE> </CODE><B>class</B><CODE> </CODE>robot<CODE> </CODE><CODE>=</CODE><CODE> </CODE>fix_robot<CODE> </CODE><B>end</B><TT>)</TT><CODE> </CODE>;;<BR># <B>module</B><CODE> </CODE>Crazy<CODE> </CODE><CODE>=</CODE><CODE> </CODE>RobotClient<CODE> </CODE><TT>(</TT><B>struct</B><CODE> </CODE><B>class</B><CODE> </CODE>robot<CODE> </CODE><CODE>=</CODE><CODE> </CODE>crazy_robot<CODE> </CODE><B>end</B><TT>)</TT><CODE> </CODE>;;<BR># <B>module</B><CODE> </CODE>Obstinate<CODE> </CODE><CODE>=</CODE><CODE> </CODE>RobotClient<CODE> </CODE><TT>(</TT><B>struct</B><CODE> </CODE><B>class</B><CODE> </CODE>robot<CODE> </CODE><CODE>=</CODE><CODE> </CODE>obstinate_robot<CODE> </CODE><B>end</B><TT>)</TT><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
The following small program provides a way to launch the server and the
various clients from the command line. The argument passed to the program
specifies which one to launch.


<PRE><BR># <B>let</B><CODE> </CODE>port<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>1</CODE><CODE>2</CODE><CODE>0</CODE><CODE>0</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>Array.length<CODE> </CODE>Sys.argv<CODE> </CODE><CODE>&gt;=</CODE><CODE>2</CODE><CODE> </CODE><B>then</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>match</B><CODE> </CODE>Sys.argv<CODE>.</CODE><TT>(</TT><CODE>1</CODE><TT>)</TT><CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>"1"</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>server<CODE> </CODE><CODE>2</CODE><CODE>5</CODE><CODE> </CODE><CODE>3</CODE><CODE>0</CODE><CODE> </CODE>port<CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><B>in</B><CODE> </CODE>s#start<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"2"</CODE><CODE> </CODE>-&gt;<CODE> </CODE>trace_client<CODE> </CODE><CODE>"localhost"</CODE><CODE> </CODE>port<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"3"</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE>o<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>Fix.robot<CODE> </CODE><CODE>"fix"</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>"localhost"</CODE><CODE> </CODE>port<CODE> </CODE><B>in</B><CODE> </CODE>o#start<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"4"</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE>o<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>Crazy.robot<CODE> </CODE><CODE>"crazy"</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>"localhost"</CODE><CODE> </CODE>port<CODE> </CODE><B>in</B><CODE> </CODE>o#start<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>"5"</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>let</B><CODE> </CODE>o<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>Obstinate.robot<CODE> </CODE><CODE>"obstinate"</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>0</CODE><CODE> </CODE><CODE>"localhost"</CODE><CODE> </CODE>port<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>o#start<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>()<CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
<A NAME="toc297"></A>
<H3> To Learn More</H3>The world of robots stimulates the imagination. With the elements already
given here, one can easily create an ``intelligent robot'' which is both a
robot and a spy. This allows the various inhabitants of the world to
cooperate. One can then extend the application to obtain a small action game
like ``chickens-foxes-snakes'' in which the foxes chase the chickens, the
snakes chase the foxes and the chickens eat the snakes.

<BR>
<BR>
<HR>
<A HREF="book-ora194.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora196.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
